//----------------------------------Include-------------------------------------
#include "mcu.h"
//------------------------------------------------------------------------------

//BL24C256
//total:       32KB (256k-bits)
//page size:   64B * 512page
//addr:        0000-7FFF

//-----------------------------------Macro--------------------------------------
#define _PAGE_BYTES          64
//------------------------------------------------------------------------------
#define _i2c_start           mcu_i2c2_start
#define _i2c_restart         mcu_i2c2_start
#define _i2c_stop            mcu_i2c2_stop
#define _i2c_tx_addr         mcu_i2c2_tx_addr
#define _i2c_tx_byte         mcu_i2c2_tx_byte
#define _i2c_rx_byte         mcu_i2c2_rx_byte
#define _delay_ms(x)         mcu_delay_ms(x)
//------------------------------------------------------------------------------

//--------------------------------Static Func-----------------------------------
static void _RdNByte_InOnePage(uint16_t addr, uint8_t* pdata, uint16_t N)
{ 
  uint16_t  i;
  
  _i2c_start();
  if(_i2c_tx_addr(0xA0) == 1) return;
  if(_i2c_tx_byte((addr>>8)&0xFF) == 1) return;
  if(_i2c_tx_byte( addr    &0xFF) == 1) return;
  
  _i2c_restart();
  if(_i2c_tx_addr(0xA1) == 1) return;
  for(i=0; i<N-1; i++){
    pdata[i] = _i2c_rx_byte(0);
  }
  pdata[i] = _i2c_rx_byte(1);  //need to send NACK
  _i2c_stop();
}

static void _WrNByte_InOnePage(uint16_t addr, uint8_t* pdata, uint16_t N)
{ 
  uint16_t  i;
  
#if 1
  static uint8_t  rd_buf[_PAGE_BYTES];
  _RdNByte_InOnePage(addr, rd_buf, N);
  for(i=0; i<N; i++){
    if(rd_buf[i] != pdata[i]) break;
  }
  if(i>=N) return;    //same
#endif
  
  _i2c_start();
  if(_i2c_tx_addr(0xA0) == 1) return;
  if(_i2c_tx_byte((addr>>8)&0xFF) == 1) return;
  if(_i2c_tx_byte( addr    &0xFF) == 1) return;
  for(i=0; i<N; i++){
    if(_i2c_tx_byte(pdata[i]) == 1) return;
  }
  _i2c_stop();
  
  _delay_ms(5);   //tWR max 3ms
}
//------------------------------------------------------------------------------

//--------------------------------Public Func-----------------------------------
void brd_init_24c256(void)
{
}

void brd_24c256_wr_one_byte(uint16_t addr, uint8_t data)
{
  _i2c_start();
  if(_i2c_tx_addr(0xA0) == 1) return;
  if(_i2c_tx_byte((addr>>8)&0xFF) == 1) return;
  if(_i2c_tx_byte( addr    &0xFF) == 1) return;
  if(_i2c_tx_byte(data) == 1) return;
  _i2c_stop();
}

uint8_t brd_24c256_rd_one_byte(uint16_t addr)
{
  uint8_t rt;
  
  _i2c_start();
  if(_i2c_tx_addr(0xA0) == 1) return 0xFF;
  if(_i2c_tx_byte((addr>>8)&0xFF) == 1) return 0xFF;
  if(_i2c_tx_byte( addr    &0xFF) == 1) return 0xFF;
  
  _i2c_restart();
  if(_i2c_tx_addr(0xA1) == 1) return 0xFF;
  rt = _i2c_rx_byte(1);
  _i2c_stop();
  
  return rt;
}

void brd_24c256_wr_n_byte(uint16_t addr, uint8_t* pdata, uint16_t len)
{ 
  uint16_t   Temp,NTail,NHead,Page;
  uint8_t*   p;
  
  Temp  = (addr + _PAGE_BYTES)/_PAGE_BYTES*_PAGE_BYTES;
  NHead = Temp - addr;
  if(NHead >= len){
    NHead = len;
    NTail = 0;
    Page = 0;
  }else{
    NTail = (addr+len)-((addr+len)/_PAGE_BYTES*_PAGE_BYTES);
    Page = (len-NHead-NTail)/_PAGE_BYTES;
  }
  p = pdata;
  Temp = addr;
  if(NHead){
    _WrNByte_InOnePage(Temp, p, NHead);
    p += NHead;
    Temp += NHead;
  }
  while(Page){
    _WrNByte_InOnePage(Temp, p, _PAGE_BYTES);
    Page--;
    p += _PAGE_BYTES;
    Temp += _PAGE_BYTES;
  }
  if(NTail){
    _WrNByte_InOnePage(Temp, p, NTail);
  }
}

void brd_24c256_rd_n_byte(uint16_t addr, uint8_t* pdata, uint16_t len)
{
  uint16_t   Temp,NTail,NHead,Page;
  uint8_t*   p;
  
  Temp  = (addr + _PAGE_BYTES)/_PAGE_BYTES*_PAGE_BYTES;
  NHead = Temp - addr;
  if(NHead >= len){
    NHead = len;
    NTail = 0;
    Page = 0;
  }else{
    NTail = (addr+len)-((addr+len)/_PAGE_BYTES*_PAGE_BYTES);
    Page = (len-NHead-NTail)/_PAGE_BYTES;
  }
  p = pdata;
  Temp = addr;
  if(NHead){
    _RdNByte_InOnePage(Temp, p, NHead);
    p += NHead;
    Temp += NHead;
  }
  while(Page){
    _RdNByte_InOnePage(Temp, p, _PAGE_BYTES);
    Page--;
    p += _PAGE_BYTES;
    Temp += _PAGE_BYTES;
  }
  if(NTail){
    _RdNByte_InOnePage(Temp, p, NTail);
  }
}
//------------------------------------EOF---------------------------------------









